import time
import uuid
import threading
from motor.utils.singleton import ThreadSafeSingleton
from motor.coordinator.models.request import RequestInfo
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class RequestManager(ThreadSafeSingleton):
    """
    Request Manager - High concurrency pure ID generation and request management
    Uses microsecond timestamp + thread-safe counter + random suffix for uniqueness
    """

    def __init__(self):
        if hasattr(self, '_initialized'):
            return
            
        # Thread-safe counter state
        self._counter = 0
        self._last_timestamp = 0
        self._lock = threading.Lock()  # Protects counter state
        
        self.__req_info_dict: dict[str, RequestInfo] = {}
        
        self._initialized = True
        logger.info("RequestManager initialized")

    def generate_request_id(self) -> str:
        """
        Generate globally unique request ID
        
        Returns:
            Pure ID string in format: timestamp(16 digits) + counter(4 digits) + random(8 chars)
        """
        try:
            # Microsecond precision timestamp
            current_timestamp = int(time.time() * 1000000)
            random_suffix = uuid.uuid4().hex[:8]
            
            with self._lock:
                if current_timestamp == self._last_timestamp:
                    self._counter += 1
                else:
                    self._counter = 0
                    self._last_timestamp = current_timestamp
                
                # Format: timestamp + counter(4 digits) + random(8 chars)
                counter_part = f"{self._counter:04d}"
                request_id = f"{current_timestamp}{counter_part}{random_suffix}"
            
            logger.debug(f"Generated request ID: {request_id}")
            return request_id
            
        except Exception as e:
            logger.error(f"Failed to generate request ID: {e}")
            # Emergency fallback
            return uuid.uuid4().hex

    def getReq(self, req_id: str) -> RequestInfo:
        """
        Get request info by ID

        Args:
            req_id (str): Request ID to retrieve

        Returns:
            RequestInfo: The request information if found, None otherwise
        """
        return self.__req_info_dict.get(req_id)

    def addReq(self, req_info: RequestInfo) -> bool:
        """
        Add request info to the global request dictionary in a thread-safe manner
        
        Args:
            req_info (RequestInfo): Request information to be added
            
        Returns:
            bool: True if successfully added, False otherwise
        """
        try:
            with self._lock:
                if req_info.req_id in self.__req_info_dict:
                    logger.warning(f"Request ID {req_info.req_id} already exists")
                    return False

                self.__req_info_dict[req_info.req_id] = req_info
            logger.debug(f"Added request info for ID: {req_info.req_id}")
            return True
        except Exception as e:
            logger.error(f"Failed to add request info for ID {req_info.req_id}: {e}")
            return False

    def delReq(self, req_id: str) -> bool:
        """
        Delete request info from the global request dictionary in a thread-safe manner
        
        Args:
            req_id (str): Request ID to be deleted
            
        Returns:
            bool: True if successfully deleted, False if ID not found or error occurred
        """
        try:
            with self._lock:
                if req_id not in self.__req_info_dict:
                    logger.warning(f"Request ID {req_id} not found for deletion")
                    return False
                
                del self.__req_info_dict[req_id]
                logger.debug(f"Deleted request info for ID: {req_id}")
                return True
        except Exception as e:
            logger.error(f"Failed to delete request info for ID {req_id}: {e}")
            return False
